﻿namespace Lilium.CSharp.Expressions.Substitutions

open System.Linq.Expressions
open System.Reflection

// провайдеры возвращают замены для каждого типа вырадения, либо None если замена не требуется.
type SubstitutionProvider = { 
    methodCall :                    // Method call substitutions
           MethodInfo               // Method being substituted 
        -> Expression               // Object expression
        -> Expression list          // Method arguments
        -> ISubstitution option     // Substitution or None if method call shoul not be substituted
    }

module Providers =

    // Возвращает замены используя рефлексию.
    let reflectedSubstitutions = {
        methodCall = fun meth obj args -> 
            match meth.GetCustomAttributes(typeof<ISubstitution>, true) |> List.ofArray with
            | subs :: [] -> Some (subs :?> ISubstitution)
            | [] -> None 
            | _ -> failwithf "Multiple substitutions reflected for method {%O}" meth
        }

    // C# Support:
    //TODO: сделать функцию для создания провайдеров из C#-а
    
    // TODO: расшиение провайдеров должно осуществляться за счет Extension методов с помощью fluent - интерфейса. Приоритет 
    // имеет последний добавляемый метод. Это позволяет взять, например reflectedSubstitutions за основу и настроить его под 
    // конкретные нужды.

